//
//  DYVideoScanManager.m
//  PrivatePhoto
//
//  Created by PrivatePhoto Team on 2021.
//  Copyright © 2021年 PrivatePhoto Team. All rights reserved.6.
//

#import "DYVideoScanManager.h"
#import "ImageCompare.h"
@interface DYVideoScanManager ()<PHPhotoLibraryChangeObserver>
@property (nonatomic, strong) PHFetchResult *assetArr;
@property (nonatomic, strong) NSMutableArray <PHAsset *>*videoArray;
@property (nonatomic, strong) PHImageRequestOptions *imageOpt;
@property (nonatomic, strong) PHImageRequestOptions *sizeOpt;
@property (nonatomic, strong) PHAsset *lastAsset;
@property (nonatomic, strong) UIImage *lastImage;
@property (nonatomic, strong) NSData *lastImageData;
@property (nonatomic, assign) CMTime  lastTime;
@property (nonatomic, assign) BOOL lastSame;

@property (nonatomic, strong) NSMutableArray *randomArray;

@property (nonatomic, copy) void (^completionHandler)(BOOL success, NSError *error);
@property (nonatomic, copy) void (^processHandler)(NSInteger current, NSInteger total);
@end
@implementation DYVideoScanManager

//+ (DYVideoScanManager *)shareManager {
//    static DYVideoScanManager *mgr = nil;
//    static dispatch_once_t token;
//    dispatch_once(&token, ^{
//        mgr = [[DYVideoScanManager alloc] init];
//    });
//    return mgr;
//}

#pragma mark - LibraryChange 相册变换通知

- (instancetype)init {
    self = [super init];
    if (self) {
        [[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self];
    }
    return self;
}

- (void)dealloc {
    [[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self];
}

- (void)photoLibraryDidChange:(PHChange *)changeInstance {
    // 筛选出没必要的变动
    PHFetchResultChangeDetails *collectionChanges =
    [changeInstance changeDetailsForFetchResult:self.assetArr];
    if (collectionChanges == nil || self.notificationStatus != CAPhotoNotificationStatusDefualt) {
        return;
    }
    
    dispatch_async(dispatch_get_main_queue(), ^{
        if ([self.delegate respondsToSelector:@selector(clearAlaumLibraryDidChange)]) {
            [self.delegate clearAlaumLibraryDidChange];
        }
    });
}

#pragma mark - GetImage 获取视频

// 加载照片
- (void)loadVideosWithProcess:(void (^)(NSInteger current, NSInteger total))process
           completionHandler:(void (^)(BOOL success, NSError *error))completion {
    [self resetTagData];
    self.processHandler = process;
    self.completionHandler = completion;
    
    // 获取当前App的相册授权状态
    PHAuthorizationStatus authorizationStatus = [PHPhotoLibrary authorizationStatus];
    // 判断授权状态
    if (authorizationStatus == PHAuthorizationStatusAuthorized) {
        // 如果已经授权, 获取图片
        [self getAllAsset];
    }
    // 如果没决定, 弹出指示框, 让用户选择
    else if (authorizationStatus == PHAuthorizationStatusNotDetermined) {
        [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
            // 如果用户选择授权, 则获取图片
            if (status == PHAuthorizationStatusAuthorized) {
                [self getAllAsset];
            }
        }];
    } else {
        [self noticeAlert];
    }
}
// 重置数据
- (void)resetTagData {
    self.videoArr = nil;
    self.videoInfo = nil;
    self.totalSpace = 0;
    self.videoArray = nil;
}

// 获取相簿中的PHAsset对象
- (void)getAllAsset {
    // 获取所有资源的集合，并按资源的创建时间排序
    PHFetchOptions *options = [[PHFetchOptions alloc] init];
    options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate"
                                                              ascending:NO]];
    PHFetchResult *result = [PHAsset fetchAssetsWithOptions:options];
    self.assetArr = result;
    for (PHAsset *asset in result) {
        if (asset.mediaType == PHAssetMediaTypeVideo) {
            [self.videoArray addObject:asset];
        }
    }
   
    [self requestImageWithIndex:0];
}

- (void)handleImageCountForRequestWithIndex:(NSInteger)index{
   
    if (index >= self.videoArray.count) {
        [self loadCompletion];
        self.completionHandler(YES, nil);
        return;
    }
    NSInteger normalCount = 0;
    NSInteger totalCount = self.videoArray.count;//self.videoArray.count;
    if (totalCount <= 100) {
        normalCount = totalCount;
    }
    normalCount = totalCount*6/10;
    if (index > normalCount && (index+5 ) <= self.videoArray.count) {
        if (!self.lastSame) {
           [self.randomArray removeAllObjects];
            while ([self.randomArray count] < 5) {
                int r = arc4random() % 5;
                [self.randomArray addObject:[self.videoArray objectAtIndex:index+r]];
            }
            [self requestImageWithAsset:self.randomArray.firstObject];
        }else{
            [self requestImageWithIndex:index];
        }
    }else{
        [self requestImageWithIndex:index];
    }
    
}

- (void)requestImageWithAsset:(PHAsset *)asset{
    NSInteger index = [self.videoArray indexOfObject:asset];
    self.processHandler(index, self.videoArray.count);
    if (index >= self.videoArray.count) {
        [self loadCompletion];
        self.completionHandler(YES, nil);
        return;
    }
    if (asset.mediaType != PHAssetMediaTypeVideo || asset.sourceType != PHAssetSourceTypeUserLibrary) {
        [self requestImageWithIndex:index+1];
        return;
    }
    // 获取缩率图
    PHImageManager *mgr = [PHImageManager defaultManager];
    __weak typeof(self) weakSelf = self;
    [mgr requestImageForAsset:asset
                   targetSize:CGSizeMake(125, 125)
                  contentMode:PHImageContentModeDefault
                      options:self.imageOpt
                resultHandler:^(UIImage *result, NSDictionary *info) {
                    [weakSelf getImageSizeWithIndex:index
                                              image:result];
                }];
}


// 获取图片
- (void)requestImageWithIndex:(NSInteger)index {

    self.processHandler(index, self.videoArray.count);//self.assetArr.count
    if (index >= self.videoArray.count) {
        [self loadCompletion];
        self.completionHandler(YES, nil);
        return;
    }
    PHAsset *a_sset = self.videoArray[index];
    if (a_sset.mediaType != PHAssetMediaTypeVideo || a_sset.sourceType != PHAssetSourceTypeUserLibrary) {
        [self requestImageWithIndex:index+1];
        return;
    }
    // 获取缩率图
    PHImageManager *mgr = [PHImageManager defaultManager];
    __weak typeof(self) weakSelf = self;
    [mgr requestImageForAsset:a_sset
                   targetSize:CGSizeMake(125, 125)
                  contentMode:PHImageContentModeDefault
                      options:self.imageOpt
                resultHandler:^(UIImage *result, NSDictionary *info) {
                    [weakSelf getImageSizeWithIndex:index
                                              image:result];
    }];
}


// 获取原图片大小
- (void)getImageSizeWithIndex:(NSInteger)index
                        image:(UIImage *)image {
    __weak typeof(self) weakSelf = self;
    PHImageManager *mgr = [PHImageManager defaultManager];

    if (@available(iOS 13, *)) {
        //self.assetArr[index]
        [mgr requestImageDataAndOrientationForAsset:self.videoArray[index] options:self.sizeOpt resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, CGImagePropertyOrientation orientation, NSDictionary * _Nullable info) {
            [weakSelf dealImageWithIndex:index image:image imageData:imageData];
        }];
    } else {
     
            [mgr requestImageDataForAsset:self.videoArray[index]
                                  options:self.sizeOpt
                            resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
                [weakSelf dealImageWithIndex:index image:image imageData:imageData];
            }];
        
    }
    
}

#pragma mark - DealImage 处理图片
// 处理相片
- (void)dealImageWithIndex:(NSInteger)index
                     image:(UIImage *)image
                 imageData:(NSData *)imageData {
    NSLog(@"原图 %.2fM，缩率图 %@", imageData.length/1024.0/1024.0, NSStringFromCGSize(image.size));
    PHAsset *asset = self.videoArray[index];
//    if (index > 0) {
        [self handleSimilarPhotoDataEventWithAsset:asset image:image imageData:imageData];
//    }else{
//        [self setLastDataWithAsset:asset image:image imgData:imageData index:index];
//    }
}

- (void)setLastDataWithAsset:(PHAsset *)asset image:(UIImage *)lastImage imgData:(NSData *)imgData index:(NSInteger)index{
    self.lastAsset = asset;
    self.lastImage = lastImage;
    self.lastImageData = imgData;
    [self handleImageCountForRequestWithIndex:index+1];
}

// 相似数据
- (void)handleSimilarPhotoDataEventWithAsset:(PHAsset *)asset
                                    image:(UIImage *)image
                                imageData:(NSData *)imageData{
    BOOL isSameTime = [self isSameDay:self.lastAsset.creationDate date2:asset.creationDate];
    //[self isSameTime:self.lastAsset.creationDate date2:asset.creationDate];
    NSInteger index = [self.videoArray indexOfObject:asset];
    
    @weakify(self)
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self getVideoPathFromPHAsset:asset Complete:^(NSString *filePatch, NSString *dTime,CMTime time){
            @strongify(self)
            dispatch_sync(dispatch_get_main_queue(), ^{
        
                if (self.lastAsset && isSameTime) {
                     BOOL img_similar = [ImageCompare isImage:self.lastImage likeImage:image];
                    if (img_similar) {
                        int new_seconds = ceil(time.value/time.timescale);
                        int last_seconds = ceil(self.lastTime.value/self.lastTime.timescale);
                        int dis_seconds =  abs(new_seconds - last_seconds);
                        BOOL video_similar = dis_seconds < 8;
                        if (video_similar) {
                            [self updateSimilarArrWithAsset:asset imageData:imageData];
                            self.lastSame = YES;
                        }else{
                            self.lastSame = NO;
                        }
                        self.lastTime = time;
                        [self setLastDataWithAsset:asset image:image imgData:imageData index:index];
                    }else {
                      self.lastSame = NO;
                      self.lastTime = time;
                      [self setLastDataWithAsset:asset image:image imgData:imageData index:index];
                    }
              }else{
                self.lastSame = NO;
                self.lastTime = time;
                [self setLastDataWithAsset:asset image:image imgData:imageData index:index];
              }
               
            });
           
        }];
    });

    
    /*
    if (self.lastAsset && isSameTime) {
         BOOL img_similar = [ImageCompare isImage:self.lastImage likeImage:image];
         if (img_similar) {
        
             @weakify(self)
             dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                 [self getVideoPathFromPHAsset:asset Complete:^(NSString *filePatch, NSString *dTime,CMTime time){
                     @strongify(self)
                     dispatch_sync(dispatch_get_main_queue(), ^{
                         int new_seconds = ceil(time.value/time.timescale);
                         int last_seconds = ceil(self.lastTime.value/self.lastTime.timescale);
                         int dis_seconds =  abs(new_seconds - last_seconds);
                         BOOL video_similar = dis_seconds >0;//< 8;
                         if (video_similar) {
                             [self updateSimilarArrWithAsset:asset imageData:imageData];
                             self.lastSame = YES;
                         }else{
                             self.lastSame = NO;
                         }
                         self.lastTime = time;
                        
                         [self setLastDataWithAsset:asset image:image imgData:imageData index:index];
                     });
                    
                 }];
             });

        }else {
            self.lastSame = NO;
            [self setLastDataWithAsset:asset image:image imgData:imageData index:index];
        }
    }else{
        self.lastSame = NO;
        [self setLastDataWithAsset:asset image:image imgData:imageData index:index];
    }
    */
}

- (void)getVideoPathFromPHAsset:(PHAsset *)asset Complete:(void (^)(NSString *filePatch,NSString *dTime,CMTime  time))result {
    PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
    options.version = PHImageRequestOptionsVersionCurrent;
    options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
    options.networkAccessAllowed = YES;
    [[PHImageManager defaultManager] requestAVAssetForVideo:asset options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
        
        NSString *sandboxExtensionTokenKey = info[@"PHImageFileSandboxExtensionTokenKey"];
        
        NSArray *arr = [sandboxExtensionTokenKey componentsSeparatedByString:@";"];
        
        NSString *filePath = arr[arr.count - 1];
        
        CMTime  time = [asset duration];
        int seconds = ceil(time.value/time.timescale);
        //format of minute
        NSString *str_minute = [NSString stringWithFormat:@"%d",seconds/60];
        //format of second
        NSString *str_second = [NSString stringWithFormat:@"%.2d",seconds%60];
        //format of time
        NSString *format_time = [NSString stringWithFormat:@"%@:%@",str_minute,str_second];

        result(filePath,format_time,time);
    }];
}


- (void)updateSimilarArrWithAsset:(PHAsset *)asset imageData:(NSData *)imageData {
    
    NSDictionary *item = @{@"asset":asset, @"space":@(imageData.length)};
    
    NSDictionary *lastDict = self.videoArr.lastObject;
    if (!self.lastSame) {
        lastDict = nil;
    }
    
    if (!lastDict) {

        NSString *keyStr = [self stringWithDate:asset.creationDate];
        if (!self.lastAsset) {
            lastDict = @{keyStr: [@[item] mutableCopy]};
        }else{
            NSDictionary *lastItem = @{@"asset":self.lastAsset, @"space":@(self.lastImageData.length)};
            lastDict = @{keyStr:[@[lastItem,item] mutableCopy]};
        }
        [self.videoArr addObject:lastDict];
    }else{

        NSMutableArray *itemArr = lastDict.allValues.lastObject;
        [itemArr addObject:item];//
        lastDict = @{lastDict.allKeys.lastObject : itemArr};
        [self.videoArr replaceObjectAtIndex:self.videoArr.count-1
                               withObject:lastDict];
        
    }
    self.totalSpace = self.totalSpace + imageData.length;
}

// 加载完成
- (void)loadCompletion {
    self.videoInfo = [self getInfoWithDataArr:self.videoArr
                                      saveSpace:self.totalSpace];
    NSLog(@"相似视频可省 ：%.2fMB", self.totalSpace / 1024.0 / 1024.0);
    NSLog(@"***ZJH 加载完成");

}

#pragma mark - Private 私有方法

- (NSDictionary *)getInfoWithDataArr:(NSArray *)dataArr
                           saveSpace:(NSUInteger)saveSpace {
    NSUInteger similarCount = 0;
    for (NSDictionary *dict in dataArr) {
        NSArray *arr = dict.allValues.lastObject;
        similarCount = similarCount + arr.count;
    }
    return @{@"count":@(similarCount), @"saveSpace" : @(saveSpace)};
}

// 是否为同一天
- (BOOL)isSameDay:(NSDate *)date1 date2:(NSDate *)date2 {
    if (!date1 || !date2) {
        return NO;
    }
    NSCalendar *calendar = [NSCalendar currentCalendar];
    unsigned unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
    NSDateComponents *comp1 = [calendar components:unitFlags fromDate:date1];
    NSDateComponents *comp2 = [calendar components:unitFlags fromDate:date2];
    return  [comp1 day] == [comp2 day] &&
            [comp1 month] == [comp2 month] &&
            [comp1 year]  == [comp2 year];
}
//是否相隔5分钟
- (BOOL)isSameTime:(NSDate *)date1 date2:(NSDate *)date2 {
    if (!date1 || !date2) {return NO;}
    long long t1 = [date1 longlongTimeIntervalSince1970];
    long long t2 = [date2 longlongTimeIntervalSince1970];
    long long tt = t1 - t2;
    long long min = [[NSNumber numberWithDouble:tt] longLongValue];
    return min <5 *60;
}

// NSDate转NSString
- (NSString *)stringWithDate:(NSDate *)date {
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"yyyy年MM月dd日"];
    return [dateFormatter stringFromDate:date];
}

// 开启权限提示
- (void)noticeAlert {
    UIAlertController *alert =
    [UIAlertController alertControllerWithTitle:@"此功能需要相册授权"
                                        message:@"请您在设置系统中打开授权开关"
                                 preferredStyle:UIAlertControllerStyleAlert];
    
    UIAlertAction *left = [UIAlertAction actionWithTitle:@"取消"
                                                   style:UIAlertActionStyleCancel
                                                 handler:nil];
    UIAlertAction *right = [UIAlertAction actionWithTitle:@"前往设置"
                                                    style:UIAlertActionStyleDefault
                                                  handler:^(UIAlertAction * _Nonnull action) {
                                                      NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
                                                      [[UIApplication sharedApplication] openURL:url];
                                                  }];
    [alert addAction:left];
    [alert addAction:right];
    UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController;
    [vc presentViewController:alert animated:YES completion:nil];
}

#pragma mark - Getter 懒加载

- (NSMutableArray *)videoArr {
    if (!_videoArr) {
        _videoArr = [NSMutableArray array];
    }
    return _videoArr;
}

- (PHImageRequestOptions *)imageOpt {
    if (!_imageOpt) {
        _imageOpt = [[PHImageRequestOptions alloc] init];
        // resizeMode 属性控制图像的剪裁
        _imageOpt.resizeMode = PHImageRequestOptionsResizeModeNone;
        // deliveryMode 则用于控制请求的图片质量
        _imageOpt.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
    }
    return _imageOpt;
}

- (PHImageRequestOptions *)sizeOpt {
    if (!_sizeOpt) {
        _sizeOpt = [[PHImageRequestOptions alloc] init];
        _sizeOpt.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
        _sizeOpt.resizeMode = PHImageRequestOptionsResizeModeExact;
    }
    return _sizeOpt;
}

- (NSMutableArray *)randomArray {
    if (!_randomArray) {
        _randomArray = [NSMutableArray array];
    }
    return _randomArray;
}

- (NSMutableArray *)videoArray{
    if (!_videoArray) {
        _videoArray = [[NSMutableArray alloc] init];
    }
    return _videoArray;
}

+ (void)tipWithMessage:(NSString *)str {
    UIAlertController *alert =
    [UIAlertController alertControllerWithTitle:@"提示"
                                        message:str
                                 preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *action =
    [UIAlertAction actionWithTitle:@"确定"
                             style:UIAlertActionStyleCancel
                           handler:nil];
    [alert addAction:action];
    
    UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController;
    [vc presentViewController:alert animated:YES completion:nil];
}

@end



